<?php

// +----------------------------------------------------------------------
// | POS机回调
// +----------------------------------------------------------------------
// | Copyright (c) 2015-2024 http://www.yicmf.com, All rights reserved.
// +----------------------------------------------------------------------
// | Author: 微尘 <yicmf@qq.com>
// +----------------------------------------------------------------------

namespace app\controller\api\notify;

use app\event\ucenter\User as UserEvent;
use app\model\pos\Pos as PosModel;
use app\model\pos\PosTrade as PosTradeModel;
use app\model\pos\Store as StoreModel;
use app\event\pos\PosTrade as PosTradeEvent;
use app\model\ucenter\User as UserModel;
use app\model\ucenter\UserMoneyLog;
use app\event\pos\Pos as PosEvent;
use think\Exception;
use think\facade\Db;

class Hw extends Common
{

    private function _getData()
    {
        $data = $this->request->param();
        unset($data['action']);
        unset($data['controller']);

        file_put_contents($this->request->action() . '.txt', json_encode($data) . "\r\n\r\n", FILE_APPEND);
        if ($this->checkRsa($data)) {
            return $data;
        } else {
            return false;
        }
    }

    /**
     * 机具绑定回调
     * https://help.jlpay.com/api/docs/document/20191015000164
     * 绑机消息推送
     * 将用户成功的绑机记录信息推送给所属服务商的平台。
     * 换机再绑的，也会再次推送新的绑机消息。
     * 字段名    变量名    必填    类型    示例值    描述
     * 手机号    phone    否    String(11)    135****6666    脱敏后的商户手机号
     * 小微商户名称    name    是    String(30)    张**    小微商户名称
     * 附加信息    supplement_info    是    String(30)    4307************48    脱敏身份信息
     * 服务商id    agentId    是    String(100)    88880019    服务商id
     * 商户号    merchNo    是    String(30)    M50000003529999    商户号，解绑后重新绑定的商户号不变
     * 终端号会变
     * 机身号    possn    是    String(50)    LD188FBMS78888    机身号
     * 机型    deviceModel    是    String(30)    NEW6220    机具型号
     * 终端号    termNo    否    String(50)    M4859999    终端号
     * 绑机时间    bindTime    是    String(50)    2019-03-12 22:21:50    绑机时间，格式为yyyy-MM-dd HH:mm:ss
     * 签名    sign    是    String(200)    eDlxE0I7WFhjeLb……
     * GhuR9A==    签名信息，需用嘉联公钥验签
     */
    public function ok()
    {

        return json('ok');
    }

    /**
     * 购买会员通知
     */
    public function vip()
    {
        $data = $this->request->param();
        file_put_contents('vip.txt', '押金缴纳 :' . json_encode($data) . "\r\n\r\n", FILE_APPEND);
        return jsonp(["ret_code" => "00", "ret_msg" => "SUCCESS"]);
    }

    /**
     * 押金缴纳通知
     */
    public function deposit()
    {
        $data = $this->request->param();
        file_put_contents('deposit.txt', '押金缴纳 :' . json_encode($data) . "\r\n\r\n", FILE_APPEND);
        return jsonp(["ret_code" => "00", "ret_msg" => "SUCCESS"]);
    }

    /**
     * 押金缴纳通知
     */
    public function cash()
    {
        $data = $this->request->param();
        file_put_contents('cash.txt', 'cash :' . json_encode($data) . "\r\n\r\n", FILE_APPEND);
        return jsonp(["ret_code" => "00", "ret_msg" => "SUCCESS"]);
    }

    /**
     * 流量费
     */
    public function flow()
    {
        $data = $this->_getData();
 
        if ($data) {
            try {
                //POS机处理
                $pos = PosModel::where('sn', $data['possn'])->find();
                if (!$pos) {
                    // 新增无主pos机
                    throw new Exception('未知');
                }
//                $pos['term_no'] = $data['termNo'];
//                $pos['merch_no'] = $data['merchNo'];
//                if (!$pos->save()) {
//                    throw new Exception('资料保存异常');
//                }
                $event = new PosEvent();
                $re = $event->flow($pos,$data['orderId'],0);
                if ($re['code'] != 0) {
                    throw new Exception($re['message']);
                }
                $rep = ['ret_code' => '00', 'ret_msg' => 'SUCCESS'];
            } catch (\Exception $e) {
                $rep = ['ret_code' => '01', 'ret_msg' => $e->getMessage()];
            }
        } else {
            $rep = ['ret_code' => '01', 'ret_msg' => 'FAIL'];
        }
        return json($rep);
    }


    /**
     * 交易流水通知
     */
    public function trade()
    {
        $data = $this->_getData();
        if ($data) {
            try {
                $trade = PosTradeModel::where('merch_no', $data['merch_no'])->where('channel_id', 0)->where('order_sn', $data['order_id'])->find();
                if ($trade) {
                    throw new Exception('已经处理');
                }
                $insert = [];
                $insert['order_sn'] = $data['order_id'];
                $insert['trans_sn'] = $data['trans_id'];
                $insert['merch_no'] = $data['merch_no'];
                $insert['busi_type'] = $data['busi_type'];
                $insert['busi_sub_type'] = $data['busi_sub_type'];
                $insert['term_no'] = $data['term_no'];
                $insert['pos_sn'] = $data['pos_sn'];
                $insert['refer_no'] = $data['refer_no'];
                $insert['card_no'] = isset($data['card_no']) ? $data['card_no'] : '';
                $insert['amount'] = round((float)$data['amount'] / 100, 2);
                $insert['lon'] = isset($data['longitude']) ? $data['longitude'] : '';
                $insert['lat'] = isset($data['latitude']) ? $data['latitude'] : '';
                $insert['pay_type'] = isset($data['pay_type']) ? $data['pay_type'] : '';
                if ($insert['pay_type'] == 'M3' || $insert['pay_type'] == '30' || $insert['pay_type'] == '31') {
                    $insert['trade_type'] = 2;
                } else {
                    $insert['trade_type'] = 1;
                }
                $insert['trans_time'] = $data['trans_time'];
                $insert['ret_code'] = $data['ret_code'];
                $insert['ret_msg'] = $data['ret_msg'];
                $insert['channel_id'] = 0;
                $insert['type'] = 1;
                $insert['channel'] = 'jl';
                if ($data['ret_code'] == '00') {
                    $insert['status'] = 1;
                } else {
                    $insert['status'] = 0;
                }
                // pos机查询
                $pos = PosModel::where('sn', $data['pos_sn'])->where('status', 1)->find();
                if ($pos) {
                    $insert['pos_id'] = $pos['id'];
                    $insert['user_id'] = $pos['user_id'];
                    $insert['store_id'] = $pos['store_id'];
                    $insert['agent_id'] = $pos['agent_id'];
                } else {
                    throw new Exception('未知');
                }
                $trade = PosTradeModel::create($insert);
                if (!$trade) {
                    throw new Exception('数据异常');
                }
                if ($data['ret_code'] == '00') {
                    $event = new PosTradeEvent();
                    $re = $event->trade($trade, $pos);
                    if ($re['code'] != 0) {
                        throw new Exception($re['message']);
                    }
                }
                $rep = ['ret_code' => '00', 'ret_msg' => 'SUCCESS'];
            } catch (\Exception $e) {
                // 回滚事务
                Db::rollback();
                $rep = ['ret_code' => '01', 'ret_msg' => $e->getMessage()];
            }
        } else {
            $rep = ['ret_code' => '01', 'ret_msg' => 'FAIL'];
        }
        return json($rep);
    }

    /**
     * 校验
     * @return void
     */
    protected function checkRsa($data)
    {
//        $str = '{"amount":"1","area_code":"440305","batch_no":"000005","busi_sub_type":"0104","card_no":"625153****0681","fee_amount":"0","merch_no":"84944038398K008","order_id":"411025775322703278899296","pay_type":"04","refer_no":"150939899296","ret_code":"00","ret_msg":"成功","term_no":"70065980","term_sn":"N5000754666","trans_time":"2020-12-21 15:09:39","vouch_no":"000187"}';
//
////        $ha = hash("sha256", $str);
////        dump($ha);
//
//        $sign = 'ofNv9baclRTDzuJR38dvj2dl6hPdTGSNYAwYnsLaowGEkJFRfFXC5Holr0/Q0KdDx0Rf+4ehKxzB/ju/38DIxK/KjZqnYFpg5m/wFXnDJZviDkM0/l+WHwZNGQzQmS5eTaH9c/Og5l++27cLc98VxYeqx46I4G1IuLDI8jFbsMbwCUr2PIGUilTA7j+bQW4SYlmEi8IQYzG8TvIZPscltM83Z4k/KEQFRPdFVE1ENrkPE50PQCwrONeDghlVOeHfRhRn5M2w/4nncQKTsptMUhBfPLwTb+SmDvSVQFjAq3MfkT3WzFRHW+AHnoybvw85jL9A623/Ru3gw6t/hUYoGA==';
//        $pb = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1TCyrEyyP292BHAM1VoWY2n9zS5MkbPsu0L/J2kHLs30vzg82/CNwnkOnYmOU9zmYQkvIhxPL3quSrcuouzbGsIwR/k/SsOXD+O2vOehAbBwdUEdy0t7XcFwnHY7D91DNeMm2j+RMS1SDmtbPcAsxluCaD/Uv0yItfHAzhon1q7Qmt1DZRAzeGqoE/DZNgZIMcsQh6SSuvcPCSOFLHtHe4t5fpO+ZdP2Ib+xbII4PBU99bq/gAVv3kGUfyNHFg3cPQ+a9yJHe/vSklpMS40dTxQpzzDmYK1//dS6Xw4TPQDt56an9QUjq+zLtuvgO7dqGYSf4sBEjILVXFeaAEIpeQIDAQAB';
        // 公钥
        $publicKey = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtudd8ePDTHrrZpmv8VU+Frxm/Y0Z5nA7/l9B58Zs9NFLzPlPij/ElJz7GA4e9evJO8ZmgyoVYa8IipZHG6lbl/FTajSnWW8WTZ+qPPZeTZ8f/tm5nepmSEqvdisdb3eoOELfIghh7N1sdeFm+kLMRFJxjx0Fpa9dwgZPOGQIW9x1uAfo3IU8whYbfBTenZQGMDoPtUoIfOYzljAYtYwg99sVI4+vWgT8V1NtDG8VqsWmLuA7iHO7da8QgRASVweEGnnj6irBa4vzA1obrevJeZ0eUL3is+c5LI4EQoxPO29ZiRYw2TScfkv8iaJ4ABagcMUowVC6a0ItUK4oHG5WEQIDAQAB\n-----END PUBLIC KEY-----"; // 替换成你的RSA公钥
//        $publicKey = "-----BEGIN PUBLIC KEY-----
//MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx+rB29mKPI8oonrNRAPe
//1c2t6Xw5gmowpJPa8LtDtmUbX3IUDbbrNHla44FKuidrPd75Ax/57ZmpPwkP/VHa
//djEWY0/dsCcQW4UWkVRFq1CN3llRldF6Zw9Vf820SDjLYMb0hVArc/7PqVrkZTxA
//qwOhKv1QVkctOjzCUDhHlPyDLpNznM65zAoBP33uRPP9cn666LBnauNkB7RFbB66
//08uHLkrUaQJqsEDCboWk/sRxKE9j9tLS0C2P6Ugu1vK4gCWhPMiOVSha1GQc6phn
//ILezWvIivHUYMoe9DlbkmEWTnz0piaCUr5Jrkd7XNxs/IY1s8F5bIgopyUHKxV+9
//ewIDAQAB
//-----END PUBLIC KEY-----"; // 替换成你的RSA公钥
        // 解析JSON
//        $jsonObj = $data;
        // 提取并显示签名字符串
        $signatureInBase64 = $data['sign'];
        if ($signatureInBase64 == 'ok') {
            return true;
        }
//        echo "签名字符串(base64): " . $signatureInBase64 . "\n";
        // 移除签名字段
        unset($data['sign']);
        // 排序原文
        ksort($data);
        $orderedJson = json_encode($data, JSON_UNESCAPED_UNICODE);
//        echo "有序原文: " . $orderedJson . "\n";
        // 对原文摘要
        $abstractOrigin = $this->sha256($orderedJson);// 注意：sha256函数返回的是十六进制字符串，不需要toHex()了
//        echo "有序原文摘要: " . $abstractOrigin . "\n";
        // 验签
        return $this->verify($publicKey, $abstractOrigin, $signatureInBase64);
    }


    /**
     * 加签
     *
     * @param string $privateKey RSA私钥
     * @param string $data 加签数据
     * @return string 签名的Base64编码
     */
    protected function sign($privateKey, $data)
    {
        $privateKeyId = openssl_pkey_get_private($privateKey);
        openssl_sign($data, $signature, $privateKeyId, OPENSSL_ALGO_SHA256);
        return base64_encode($signature);
    }

    /**
     * 验证数字签名
     *
     * @param string $publicKey RSA公钥
     * @param string $data 原文
     * @param string $signature 签名的Base64编码
     * @return bool 验证是否成功
     */
    protected function verify($publicKey, $data, $signature)
    {
        $publicKeyId = openssl_pkey_get_public($publicKey);
        $result = openssl_verify($data, base64_decode($signature), $publicKeyId, OPENSSL_ALGO_SHA256);
        return $result === 1;
    }

    /**
     * 使用sha256算法进行数据摘要
     *
     * @param string $data 摘要原文
     * @return string 摘要的Hex编码
     */
    protected function sha256($data)
    {
        return hash('sha256', $data, false);
    }

}
